package com.qzdatasoft.mcp.demo.client.test;

import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
import io.modelcontextprotocol.client.transport.ServerParameters;
import io.modelcontextprotocol.client.transport.StdioClientTransport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.CommandLineRunner;

import java.io.File;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;

@Slf4j
//@Service
public class ClientToolsStdio4Demo implements CommandLineRunner {

    private final List<McpSyncClient> mcpSyncClients;

    public ClientToolsStdio4Demo(ObjectProvider<List<McpSyncClient>> mcpSyncClientsProvider) {
        this.mcpSyncClients = mcpSyncClientsProvider.getIfAvailable();
    }

    public void run(String... args) {

        process("qzone-stdio-demo", new DemoMcpServerTest());
        process("qzone-stdio-mysql", new MysqlMcpServerTest());
        process("qzone-sse-mysql", new MysqlMcpServerTest());

    }

    private  <T extends IMcpServerTest> void process(String mcpServername, T mcpServerTest) {
        getMcpSyncClient(mcpServername).ifPresent(mcpSyncClient -> {
            try (mcpSyncClient) {
                mcpServerTest.setMcpSyncClient(mcpSyncClient).call();
                System.out.println("Done.");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    private Optional<McpSyncClient> getMcpSyncClient(String name) {
        AtomicReference<Optional<McpSyncClient>> op = new AtomicReference<>(mcpSyncClients.stream()
                .filter(mcpSyncClient -> mcpSyncClient.getClientInfo().name().endsWith(name))
                .findFirst());

        op.get().ifPresentOrElse(
            mcpSyncClient -> {
                if(!mcpSyncClient.isInitialized()) {
                    try  {
                        log.warn("McpSyncClient[{}] is initializing...", name);
                        mcpSyncClient.initialize();
                    } catch (Exception e) {
                        op.set(Optional.empty());
                        log.warn("McpSyncClient[{}] initialize failed.", name);
                        //e.printStackTrace();
                    }
                }
            },
            () -> log.warn("McpSyncClient[{}] is not exist.", name)
        );
        return op.get();
    }

    // 未使用的备忘代码：手写 McpClient 调用 McpServer 的工具
    static class CustomMcpClientConfig {
        static void sseProcess(Function<McpSyncClient, Void> callback) {
            var transport = HttpClientSseClientTransport.builder("http://127.0.0.1:8090");
            try (var client = McpClient.sync(transport.build()).build()) {
                client.initialize();
                callback.apply(client);
            }
        }

        static void stdioProcess(Function<McpSyncClient, Void> callback) {
            System.out.println(System.getProperty("user.dir"));
            String target = "qzone-demo-mcp-server-bootstrap/target/qzone-demo-mcp-server-bootstrap-0.0.1-SNAPSHOT.jar";
            if (new File(target).exists()) {
                System.out.println("Found " + target);
            } else {
                System.out.println("Not found " + target);
            }
            var stdioParams = ServerParameters.builder("java")
                    .args("-jar", target)
                    .build();

            var transport = new StdioClientTransport(stdioParams);
            transport.setStdErrorHandler(System.out::println);
            try (var client = McpClient.sync(transport).build()) {
                client.initialize();
                callback.apply(client);
            }
        }
    }

}
